package com.jade.bss.admin.grant.impl;

import java.util.List;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.jade.bss.admin.AdminException;
import com.jade.bss.admin.grant.GrantDao;
import com.jade.bss.admin.grant.GrantEntry;
import com.jade.framework.base.criterion.sql.SqlUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;

/**
 * 采用JPA实现的授权实体数据接口。
 *
 * @author sky
 * @version 1.0 13-4-18 上午9:54
 */
@Named ("bss_grantDao")
public class JpaGrantDao implements GrantDao
{
    @PersistenceContext (unitName = "default")
    protected EntityManager em;

    @SuppressWarnings (value = "unchecked")
    @Cacheable (value = "bss.grant.l", key = "#principalType + '_' + #principalName")
    public List<GrantEntry> listGrant(String principalType, String principalName)
    {
        String sql = "SELECT grant FROM GrantEntry grant WHERE principalType=:principalType AND principalName=:principalName ";
        Query query = em.createQuery(sql);
        query.setParameter("principalType", principalType);
        query.setParameter("principalName", principalName);
        return query.getResultList();
    }

    @Cacheable (value = "bss.grant.l", key = "#principalType + '_' + #principalName + '_' + #entryType")
    public List<GrantEntry> listGrant(String principalType, String principalName, String entryType)
    {
        String sql = "SELECT grant FROM GrantEntry grant WHERE principalType=:principalType AND " +
                     "principalName=:principalName AND entryType=:entryType";
        Query query = em.createQuery(sql);
        query.setParameter("principalType", principalType);
        query.setParameter("principalName", principalName);
        query.setParameter("entryType", entryType);
        return query.getResultList();
    }

    public List<GrantEntry> listGrantFromEntry(String entryType, String entryId)
    {
        String sql = "SELECT grant FROM GrantEntry grant WHERE entryType=:entryType AND entryId=:entryId";
        Query query = em.createQuery(sql);
        query.setParameter("entryType", entryType);
        query.setParameter("entryId", entryId);
        return query.getResultList();
    }

    @SuppressWarnings (value = "unchecked")
    @Cacheable (value = "bss.grant.g",
                key = "#principalType + '_' + #principalName + '_' + #entryType + '_' + #entryId")
    public GrantEntry getGrant(String principalType, String principalName, String entryType, int entryId)
    {
        String sql = "SELECT grant FROM GrantEntry grant WHERE principalType=:principalType AND " +
                     "principalName=:principalName AND entryType=:entryType AND entryId=:entryId";
        Query query = em.createQuery(sql);
        query.setParameter("principalType", principalType);
        query.setParameter("principalName", principalName);
        query.setParameter("entryType", entryType);
        query.setParameter("entryId", entryId);
        return SqlUtils.getSingleResult(query);
    }

    @Caching (evict = {@CacheEvict (value = "bss.grant.g",
                                    key = "#grant.principalType + '_' + #grant.principalName + '_' + #grant.entryType + '_' + #grant.entryId"),
                       @CacheEvict (value = "bss.grant.l", allEntries = true)})
    public void addGrant(GrantEntry grant)
            throws AdminException
    {
        em.persist(grant);
    }

    @Caching (evict = {@CacheEvict (value = "bss.grant.g",
                                    key = "#principalType + '_' + #principalName + '_' + #entryType + '_' + #entryId"),
                       @CacheEvict (value = "bss.grant.l", allEntries = true)})
    public void removeGrant(String principalType, String principalName, String entryType, int entryId)
            throws AdminException
    {
        String sql = "DELETE FROM GrantEntry WHERE principalType=:principalType AND " +
                     "principalName=:principalName AND entryType=:entryType AND entryId=:entryId";
        Query query = em.createQuery(sql);
        query.setParameter("principalType", principalType);
        query.setParameter("principalName", principalName);
        query.setParameter("entryType", entryType);
        query.setParameter("entryId", entryId);
        query.executeUpdate();
    }

    @Caching (evict = {@CacheEvict (value = "bss.grant.g", allEntries = true),
                       @CacheEvict (value = "bss.grant.l", allEntries = true)})
    public void removeGrant(String principalType, String principalName, String entryType)
            throws AdminException
    {
        String sql = "DELETE FROM GrantEntry WHERE principalType=:principalType AND " +
                     "principalName=:principalName AND entryType=:entryType";
        Query query = em.createQuery(sql);
        query.setParameter("principalType", principalType);
        query.setParameter("principalName", principalName);
        query.setParameter("entryType", entryType);
        query.executeUpdate();
    }

    @Caching (evict = {@CacheEvict (value = "bss.grant.g", allEntries = true),
                       @CacheEvict (value = "bss.grant.l", allEntries = true)})
    public void removeGrantFromEntry(String entryType, int entryId)
            throws AdminException
    {
        String sql = "DELETE FROM GrantEntry WHERE entryType=:entryType AND entryId=:entryId";
        Query query = em.createQuery(sql);
        query.setParameter("entryType", entryType);
        query.setParameter("entryId", entryId);
        query.executeUpdate();
    }
}
